﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;

namespace ChatClient
    
{
    public partial class MainWindow : Form
    {
        private MessageClient client;
        private LoginForm loginForm;
        private List<ChatWindow> groupChatWindows;
        private char SPLIT_CHAR;

        private String username;

        public MainWindow()
        {
            groupChatWindows = new List<ChatWindow>();
            loginForm = new LoginForm(this);

            client = new MessageClient();
            SPLIT_CHAR = client.getSplitChar();

            client.updateGroupChat += client_updateGroupChat;

            client.confirmLogin += client_confirmLogin;
            client.rejectLogin += client_rejectLogin;
            client.showShutdownPopup += client_showShutdownPopup;

            client.promptChatroomListUpdate += client_updateChatroomList;

            InitializeComponent();
            this.Hide();
        }

        internal MessageClient getMessageClient()
        {
            return this.client;
        }

        public void setServerAddress(String serverAddressString)
        {
            client.setServerAddress(serverAddressString);
        }

        public void loginClient(String _username)
        {
            this.username = _username;
            client.Start();

            if (!client.isRunning())
            {
                this.Hide();
                loginForm.showWarning("Server unreachable");
                loginForm.Show();
                return;
            }

            username = client.sanitiseUsername(username);
            client.requestLogin(username);
        }

        public void activateWindow()
        {
            BeginInvoke((MethodInvoker)delegate
            {
                this.Text = "JCU Mailman - Logged in as " + username;
                this.Show();
                this.Enabled = true;
                userDropList.Enabled = false;
                client.requestChatroomList();
            });
        }

        public void client_confirmLogin()
        {
            BeginInvoke((MethodInvoker)delegate
            {
                loginForm.Hide();
                activateWindow();
            });
        }

        public void client_rejectLogin()
        {
            client.Stop();
            BeginInvoke((MethodInvoker)delegate
            {
                this.Hide();
                loginForm.showWarning("Error logging in");
                loginForm.Show();
            });
        }

        private void MainWindow_Load(object sender, EventArgs e)
        {
            this.Hide();
            loginForm.ShowDialog();
        }

        /** 
         * Close all windows when the main window is closed.
         */
        private void MainWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }

        /** 
         * Create a new private chat window.
         */
        public void createGroupWindow(String chatroomName)
        {
            // Exit early if the window already exists.
            if (findGroupWindow(chatroomName) != -1)
                return;
     
            ChatWindow groupWindow = new ChatWindow(this, chatroomName);
            this.groupChatWindows.Add(groupWindow);

            Thread chatroomThread = new Thread(() =>
            {
                groupWindow.ShowDialog();

                // Remove the window from the active chat list after it has been closed.
                System.Diagnostics.Debug.WriteLine(groupChatWindows.ToString());
                groupChatWindows.Remove(groupWindow);
                System.Diagnostics.Debug.WriteLine(groupChatWindows.ToString());
                //groupChatWindows.RemoveAt(findGroupWindow(chatroomName));

            });
            chatroomThread.IsBackground = true;
            chatroomThread.Start();
        }

        /**
         * Find the index of an open group chat window in the group chat window list.
         * @return The index of the group chat window. Index is -1 if not found.
         */
        private int findGroupWindow(string chatroomName)
        {
            for (int i = 0; i < groupChatWindows.Count; i++)
            {
                if (groupChatWindows[i].getName().Equals(chatroomName))
                    return i;
            }
            return -1;
        }

        public void client_updateGroupChat(String destination, String message)
        {
            int windowNumber = findGroupWindow(destination);
            if (windowNumber >= 0)
            {
                groupChatWindows[windowNumber].appendChatLine(message);
            }
        }

        public void client_updateChatroomList()
        {
            BeginInvoke((MethodInvoker)delegate
            {
                userDropList.Enabled = true;
                userDropList.DataSource = client.getChatroomList();
                userDropList.Update();
            });

        }

        /**
         * Create a new chat window for the selected chat room.
         */
        private void privateChatBtn_Click(object sender, EventArgs e)
        {
            try
            {
                String chatroomName = userDropList.SelectedItem.ToString();
                createGroupWindow(chatroomName);
                System.Diagnostics.Debug.WriteLine("new window: " + chatroomName);
            }
            catch (NullReferenceException ex)
            { }
        }

        /**
         * Stop the chat client when the main window is closing.
         */
        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            client.Stop();
        }

        /**
         * Show a popup dialog box containing a shutdown message from the server.
         * The client will close after the message has been confirmed.
         */
        public void client_showShutdownPopup(String shutdownMessage)
        {
            const string caption = "Client Disconnected";
            var result = MessageBox.Show(shutdownMessage, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);

            BeginInvoke((MethodInvoker)delegate
            { this.Close(); });
        }
    }
}
